package org.chen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import org.chen.common.*;
import org.chen.mapper.VerificationCodeMapper;
import org.chen.service.ChatHistoryService;
import org.chen.service.UserQueryService;
import org.chen.service.UserWithChatService;
import org.chen.service.VerificationCodeService;
import org.chen.utils.EmailConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodeMapper, VerificationCode> implements VerificationCodeService {
    @Resource
    private JavaMailSender mailSender;

    @Autowired
    private VerificationCodeMapper codeRepository;

    @Autowired
    private EmailConfig emailConfig;

    @Autowired
    private UserQueryService userQueryService;

    @Autowired
    private ChatHistoryService chatHistoryService;

    @Autowired
    private UserWithChatService userWithChatService;

    @Override
    public VerificationCode findByEmailAndCode(String email, String code) {
        return codeRepository.selectOne(new QueryWrapper<VerificationCode>().eq("email", email).eq("code", code));
    }

    @Override
    public VerificationCode findTopByEmailOrderByExpiryDateDesc(String email) {
        List<VerificationCode> verificationCodes = codeRepository.selectList(new QueryWrapper<VerificationCode>().eq("email", email).orderByDesc("expiryDate"));

        if (verificationCodes.isEmpty()){
            return null;
        }
        return verificationCodes.get(0);
    }

    public void sendVerificationCode(String email) {
        if (!canSendCode(email)) {
            throw new RuntimeException("Too many requests. Please wait before sending another code.");
        }
        if (email.trim().equals("")){
            throw new RuntimeException("Cannot be empty.");
        }
        String code = UUID.randomUUID().toString().substring(0, 6); // Generate a random code
        LocalDateTime expiryDate = LocalDateTime.now().plusMinutes(5); // Set expiry date to 5 minutes from now
        String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault()).format(new Date());
        // Save the code and expiry date in the database
        VerificationCode verificationCode = new VerificationCode();
        verificationCode.setEmail(email);
        verificationCode.setCode(code);
        verificationCode.setExpiryDate(expiryDate);
        codeRepository.insert(verificationCode);

        String emailSubject = "Cancel your account";
        String emailContent = "<h3>\n" +
                "\t<span style=\"font-size:16px;\">Dear user</span> \n" +
                "</h3>\n" +
                "<p>\n" +
                "\t<span style=\"font-size:14px;\">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style=\"font-size:14px;\">&nbsp; <span style=\"font-size:16px;\">&nbsp;&nbsp;Hello! You are conducting email verification, and the verification code for this request is:<span style=\"font-size:24px;color:#FFE500;\"> "+verificationCode.getCode()+"</span> This verification code is valid within 5 minutes. Please complete the verification within 5 minutes. (Please do not disclose this verification code) If it was not done by myself, please ignore this email. This is an automatically sent email, please do not reply directly</span></span>\n" +
                "</p>\n" +
                "<p style=\"text-align:right;\">\n" +
                "\t<span style=\"background-color:#FFFFFF;font-size:16px;color:#000000;\"><span style=\"color:#000000;font-size:16px;background-color:#FFFFFF;\"><span class=\"token string\" style=\"font-family:&quot;font-size:16px;color:#000000;line-height:normal !important;background-color:#FFFFFF;\">Blink Chat</span></span></span> \n" +
                "</p>\n" +
                "<p style=\"text-align:right;\">\n" +
                "\t<span style=\"background-color:#FFFFFF;font-size:14px;\"><span style=\"color:#FF9900;font-size:18px;\"><span class=\"token string\" style=\"font-family:&quot;font-size:16px;color:#000000;line-height:normal !important;\"><span style=\"font-size:16px;color:#000000;background-color:#FFFFFF;\">"+time+"</span><span style=\"font-size:18px;color:#000000;background-color:#FFFFFF;\"></span></span></span></span> \n" +
                "</p>";

        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");;
            helper.setTo(email);
            helper.setFrom(new InternetAddress(emailConfig.getEmailFrom(), "Blink Chat", "UTF-8"));
            helper.setSubject(emailSubject);
            helper.setText(emailContent, true);
            mailSender.send(message);
        } catch (MessagingException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    public ApiResponse verifyCode(String email, String code, String name, String type) {
        if (email.trim().equals("") || code.trim().equals("") || name.trim().equals("") || type.trim().equals("")){
            throw new RuntimeException("Cannot be empty.");
        }
        VerificationCode verificationCodeOpt = findByEmailAndCode(email, code);
        if (verificationCodeOpt != null) {
            boolean after = verificationCodeOpt.getExpiryDate().isAfter(LocalDateTime.now());
            if (!after){
                return new ApiResponse(false,"Invalid or expired code.",null);
            }

            UserWithChat one = userWithChatService.getOne(new QueryWrapper<UserWithChat>().eq("name", name).eq("email", email));
            if (one == null){
                return new ApiResponse(false,"Not Found",null);
            }

            if (!type.equals("deleteDataOnly")) {
                userWithChatService.remove(new QueryWrapper<UserWithChat>().eq("objectId", one.getObjectId()));
            }
            userQueryService.remove(new QueryWrapper<UserQuery>().eq("userId",one.getObjectId()));
            chatHistoryService.remove(new QueryWrapper<ChatHistory>().eq("userId",one.getObjectId()));
            return new ApiResponse(true,"Code verified successfully.The account has been cancelled.",null);
        }else {
            return new ApiResponse(false, "Invalid or expired code.", null);
        }
    }

    public boolean canSendCode(String email) {
        VerificationCode lastCode = findTopByEmailOrderByExpiryDateDesc(email);
        if (lastCode != null) {
            LocalDateTime lastSent = lastCode.getExpiryDate().minusMinutes(5); // 获取上一次发送时间
            return LocalDateTime.now().isAfter(lastSent.plusSeconds(60)); // 检查是否已经过了60秒
        }
        return true; // 如果没有找到记录，表示可以发送
    }
}
